<?php

namespace App\Http\Controllers\Manage;

use App\Http\Controllers\ApiController;
use App\Http\Requests\DrugStoreRequest;
use App\Http\Requests\PatientOrRecordRequest;
use App\Models\DrugDictionary;
use App\Project\Traits\PinYinSearchAble;
use App\Project\Traits\SearchAble;
use App\Transformers\DrugsOfRecordTransformer;
use App\Transformers\MedicalDrugTransformer;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use League\Fractal\Resource\Item;

/**
 * 药品相关控制器
 * Class DrugController
 * @package App\Http\Controllers\Manage
 */
class DrugController extends ApiController
{
    use PinYinSearchAble;

    protected $searchQueryMap = [
        'name'    => ['field' => 'name', 'operator' => 'like'],
        'group'   => ['field' => 'group', 'operator' => '='],
        'type'    => ['field' => 'type', 'operator' => '='],
        'insulin' => ['field' => 'is_insulin', 'operator' => '='],
    ];

    /**
     * 药品列表
     * @param \Illuminate\Http\Request   $request
     * @param \App\Models\DrugDictionary $dictionary
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Validation\ValidationException
     */
    public function index(Request $request, DrugDictionary $dictionary)
    {
        $input = $request->input();

        $validator = $this->searchQueryValidator($input, $request);

        if ($validator->fails()) {
            throw new ValidationException($validator, $this->buildFailedValidationResponse(
                $request, $this->formatValidationErrors($validator)
            ));
        }

        $size = $request->get('size');

        if (is_null($size)) {
            $data = $this->pinYinSearch($input, $dictionary)->get();

            /** @var \Illuminate\Database\Eloquent\Collection $data */
            return $this->collection($data, new MedicalDrugTransformer());
        } else {
            $data = $this->pinYinSearch($input, $dictionary)->paginate($size)->appends($input);

            /** @var \Illuminate\Pagination\LengthAwarePaginator $data */
            return $this->paginate($data, new MedicalDrugTransformer());
        }
    }

    /**
     * 搜索参数验证
     * @param $input
     * @return \Illuminate\Validation\Validator
     */
    protected function searchQueryValidator($input, Request $request)
    {
        return \Validator::make(
            $input,
            [
                'size'  => 'nullable|integer|min:10',
                'group' => 'nullable|integer|min:1',
                'type'  => 'nullable|integer|in:1,2,3',
            ], [
                'size.integer'  => '每页数量 必须是整数。',
                'size.min'      => '每页数量 最少10条。',
                'group.integer' => '分组ID 必须是整数。',
                'group.min'     => '分组ID 最小是1。',
            ]
        )->sometimes('name', 'required_without:group', function () use ($request) {

            return $request->input('size') ? false : true;
        });
    }

    /**
     * 添加药品
     * @param \App\Http\Requests\DrugStoreRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function store(DrugStoreRequest $request)
    {
        $input = $request->input();

        $drug = DrugDictionary::create($input);

        return $this->response(['id' => $drug]);
    }

    /**
     * 编辑药品页面的信息显示
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function edit(Request $request)
    {
        $id = $request->get('id');

        $data = DrugDictionary::findOrFail($id);

        return $this->item($data, (new MedicalDrugTransformer())->setDefaultIncludes(['detail']));
    }

    public function update()
    {
    }

    /**
     * 返回药物分组信息
     * @return \Illuminate\Http\JsonResponse
     */
    public function group()
    {
        return $this->response(
            collect(app('field')->get('drug.group.2'))->map(function ($group, $key) {

                return ['key' => $key, 'value' => $group];
            })
        );
    }

    public function exists(Request $request)
    {
        $this->validate($request, [
            'name' => 'required'
        ]);

        $where = $this->parseSearchQueryToWhere(
            $request->all(),
            [
                'name'    => ['field' => 'name', 'operator' => '='],
                'type'    => ['field' => 'type', 'operator' => '='],
                'insulin' => ['field' => 'is_insulin', 'operator' => '='],
            ]
        );

        $result = DrugDictionary::where($where)->exists();

        return $this->response(['exists' => $result]);
    }

    /**
     * 获取用药 方法 （现病史，既往史，处理）
     * @param \App\Http\Requests\PatientOrRecordRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function drugsOfRecord(PatientOrRecordRequest $request)
    {
        try {

            $data = new Item([], new DrugsOfRecordTransformer(
                $request->input('record_id'), $request->input('patient_id')
            ));
        } catch (\InvalidArgumentException $exception) {
            return $this->setMessage($exception->getMessage())
                        ->setCode(40400)
                        ->hasNoData();
        }

        $data = $this->fractal->createData($data)->toArray();

        $includes = $this->fractal->getRequestedIncludes();

        if (count($includes) === 1) {
            $data = $data[$includes[0]];
        }

        if (array_key_exists('medication', $data) && !empty($data['medication'])) {
            $collection = collect($data['medication']);

            $drugs = DrugDictionary::whereIn('name', $collection->pluck('name')->toArray())
                                   ->select(['name', 'is_insulin'])->withTrashed()
                                   ->get()->keyBy('name');

            $data['medication'] = $collection->reject(function ($medication) {
                return $medication == '';
            })->map(function ($medication) use ($drugs) {
                if ($drug = $drugs->get($medication['name'])) {
                    /** @var DrugDictionary $drug */
                    $medication['insulin'] = $drug->isInsulin();
                } else {
                    $medication['insulin'] = null;
                }
                return $medication;
            })->toArray();
        }

        return $this->response($data);
    }
}
